package net.csdn.business.notify.common.interceptor.impl;

import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson2.JSON;
import net.csdn.business.notify.common.annotation.RepeatSubmit;
import net.csdn.business.notify.common.constant.CommonConstants;
import net.csdn.business.notify.common.filter.RepeatedlyRequestWrapper;
import net.csdn.business.notify.common.interceptor.IRepeatSubmitConfig;
import net.csdn.business.notify.common.interceptor.RepeatSubmitInterceptor;
import net.csdn.business.notify.common.redis.RedisCache;
import net.csdn.business.notify.common.utils.HttpHelper;
import net.csdn.business.notify.common.utils.IpUtil;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author likun
 * @date 2022/6/6 19:49
 */
public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
    public final String REPEAT_PARAMS = "repeatParams";
    public final String REPEAT_TIME = "repeatTime";

    private final RedisCache redisCache;
    private final IRepeatSubmitConfig config;

    public SameUrlDataInterceptor(RedisCache redisCache, IRepeatSubmitConfig config) {
        this.redisCache = redisCache;
        this.config = config;
    }

    @Override
    public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) {
        String nowParams = "";
        if (request instanceof RepeatedlyRequestWrapper) {
            RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
            nowParams = HttpHelper.getBodyString(repeatedlyRequest);
        }

        // body参数为空，获取Parameter的数据
        if (StringUtils.isEmpty(nowParams)) {
            nowParams = JSON.toJSONString(request.getParameterMap());
        }
        // 使用摘要降低内存占用
        nowParams = DigestUtil.md5Hex(nowParams);
        // uuid没有的情况使用IP作为key,降低误判率
        String cacheRepeatKey = this.getCacheKey(request);
        Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
        if (sessionObj != null) {
            String preParams = ((String) sessionObj);
            if (nowParams.equals(preParams)) {
                return true;
            }
        }
        redisCache.setCacheObject(cacheRepeatKey, nowParams, annotation.interval(), TimeUnit.MILLISECONDS);
        return false;
    }

    @Override
    public boolean isEnabled() {
        return this.config.isEnabled();
    }

    private String getCacheKey(HttpServletRequest request) {
        // 请求地址（作为存放cache的key值）
        String url = request.getRequestURI();

        // 唯一值（没有消息头则使用请求地址）
        String submitKey = StringUtils.trimToEmpty(request.getHeader(this.getHeaderKey()));

        // 唯一标识（指定key + url + 消息头）, 消息头为空使用IP，降低误判率
        return CommonConstants.REPEAT_SUBMIT_KEY + DigestUtil.md5Hex(url + CommonConstants.UNDERLINE + (StringUtils.isBlank(submitKey) ? IpUtil.getIp() : submitKey));
    }

    private String getHeaderKey() {
        String key = this.config.getTokenHeaderKey();
        return StringUtils.isNotBlank(key) ? key : "uuid";
    }

    /**
     * 判断参数是否相同
     */
    private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap) {
        String nowParams = (String) nowMap.get(REPEAT_PARAMS);
        String preParams = (String) preMap.get(REPEAT_PARAMS);
        return nowParams.equals(preParams);
    }

    /**
     * 判断两次间隔时间
     */
    private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval) {
        long time1 = (Long) nowMap.get(REPEAT_TIME);
        long time2 = (Long) preMap.get(REPEAT_TIME);
        return (time1 - time2) < interval;
    }
}